//===============================================================================
// Microsoft patterns & practices Enterprise Library Contribution
// Mapping Application Block
//===============================================================================

using System;
using System.Globalization;
using System.Collections.Generic;
using System.Windows.Forms;
using Microsoft.Practices.EnterpriseLibrary.Configuration.Design;
using EntLibContrib.Mapping.Configuration.Design.Generators;
using EntLibContrib.Mapping.Properties;

namespace EntLibContrib.Mapping.Configuration.Design
{
	/// <summary>
	/// Generate mappers node command
	/// </summary>
	/// <remarks>This command will generate mappers from a selected assembly containing
	/// classes decorated with the MapperClassAttribute and MapperPropertyAttribute</remarks>
	public class GenerateMappersNodeCommand : ConfigurationNodeCommand
	{
		#region Construction
		/// <summary>
		/// Initializes a new instance of the <see cref="GenerateMappersNodeCommand"/> class.
		/// </summary>
		/// <param name="serviceProvider">The service provider.</param>
		public GenerateMappersNodeCommand(IServiceProvider serviceProvider)
			: base(serviceProvider)
		{ }
		#endregion

		#region Public Methods
		/// <summary>
		/// When overridden by a class, executes the core logic of the command.
		/// </summary>
		/// <param name="node">The node to execute the command upon.</param>
		protected override void ExecuteCore(ConfigurationNode node)
		{
			MappingSettingsNode sourceNode = node as MappingSettingsNode;
			if (sourceNode != null)
			{
				// check for dirty and ask for saving
				if (UIService.IsDirty(node.Hierarchy))
				{
					DialogResult result = UIService.ShowMessage(InternalResources.SaveApplicationBeforeGeneratingMappersRequest,
																											InternalResources.SaveApplicationCaption,
																											MessageBoxButtons.YesNo);
					if (DialogResult.Yes == result)
					{
						if (!TryAndSaveApplication(node))
							return;
					}
				}

				TryAndGenerateMappers(sourceNode);
			}
		}
		#endregion

		#region Private Methods
		private bool TryAndSaveApplication(ConfigurationNode node)
		{
			SaveConfigurationApplicationNodeCommand cmd = new SaveConfigurationApplicationNodeCommand(ServiceProvider);
			cmd.Execute(node);
			return cmd.SaveSucceeded;
		}

		private static void TryAndGenerateMappers(MappingSettingsNode sourceNode)
		{
			try
			{
				// get the assembly
				OpenFileDialog dialog = new OpenFileDialog();
				dialog.Title = InternalResources.OpenAssemblyDialogTitle;
				dialog.Filter = InternalResources.OpenAssemblyDialogFilter;
				dialog.AddExtension = true;
				dialog.CheckPathExists = true;
				if (dialog.ShowDialog() == DialogResult.OK)
				{
					// get the assembly file name
					string assemblyFileName = dialog.FileName;
					if (String.IsNullOrEmpty(assemblyFileName))
						MessageBox.Show(InternalResources.MissingAssemblyFile, InternalResources.MappingBlockName, MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
					else
					{
						// build the mapper nodes
						Dictionary<string, MapperBaseNode> generatedMapperNodes = MapperBuilder.Build(assemblyFileName);
						if (generatedMapperNodes.Count > 0)
						{
							var mapperNames = new List<string>();
							foreach (ConfigurationNode mapperNode in sourceNode.Nodes)
							{
								mapperNames.Add(mapperNode.Name);
							}
							foreach (string mapperName in mapperNames)
							{
								if (generatedMapperNodes.ContainsKey(mapperName))
									sourceNode.Nodes[mapperName].Remove();
							}
							foreach (KeyValuePair<string, MapperBaseNode> generatedMapperNode in generatedMapperNodes)
							{
								sourceNode.AddNode(generatedMapperNode.Value);
							}
							MessageBox.Show(String.Format(CultureInfo.CurrentCulture, InternalResources.GenerateMappersComplete, generatedMapperNodes.Count), InternalResources.MappingBlockName, MessageBoxButtons.OK, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1);
						}
						else
							MessageBox.Show(InternalResources.NoMappersFound, InternalResources.MappingBlockName, MessageBoxButtons.OK, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1);
					}
				}
			}
			catch (ApplicationException exception)
			{
				MessageBox.Show(exception.Message, InternalResources.MappingBlockName, MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
			}
		}
		#endregion
	}
}
